﻿using Server.Framework.Message;
using Server.Framework.Util;
using SuperSocket.SocketBase.Protocol;
using System;

namespace Server.Framework.Socket
{
    /// <summary>
    /// Author: Leil
    /// Description: 自定义消息序列化规则
    /// CreateTime: 2020/5/11 15:32:39
    /// </summary>
    class ProtobufReceiveFilter : IReceiveFilter<ProtobufRequestInfo>
    {
        public int LeftBufferSize { get; }

        public IReceiveFilter<ProtobufRequestInfo> NextReceiveFilter { get; }

        public FilterState State { get; }

        private byte[] swapBuffer;

        private int sumLength = 0;

        private int alreadySwap = 0;


        /// <summary>
        /// 该方法将会在 SuperSocket 收到一块二进制数据时被执行，接收到的数据在 readBuffer 中从 offset 开始， 长度为 length 的部分
        /// </summary>
        /// <param name="readBuffer">接收缓冲区, 接收到的数据存放在此数组里</param>
        /// <param name="offset">接收到的数据在接收缓冲区的起始位置</param>
        /// <param name="length">本轮接收到的数据的长度</param>
        /// <param name="toBeCopied">表示当你想缓存接收到的数据时，是否需要为接收到的数据重新创建一个备份而不是直接使用接收缓冲区</param>
        /// <param name="rest">接收缓冲区还剩余多少数据未被解析</param>
        /// <returns>序列化后消息</returns>
        public ProtobufRequestInfo Filter(byte[] readBuffer, int offset, int length, bool toBeCopied, out int rest)
        {
            rest = 0;
            // 消息头16个字节
            if (length < 16) { return default; }
            
            if (sumLength == 0)
            {
                int bodyLength = BufferUtil.GetInt(readBuffer, offset + 12);
                sumLength = 16 + bodyLength;
                swapBuffer = new byte[sumLength];
            }
            if (alreadySwap + length <= sumLength)
            {
                Array.Copy(readBuffer, offset, swapBuffer, alreadySwap, length);
                alreadySwap += length;
            } else
            {
                int copyLength = sumLength - alreadySwap;
                Array.Copy(readBuffer, offset, swapBuffer, alreadySwap, copyLength);
                alreadySwap += copyLength;
                rest = length - copyLength;
            }

            if (alreadySwap >= sumLength)
            {
                RequestBaseMessage message = MessageDecoder.Decode(swapBuffer, 0);
                if (message == null) { return default; }
                ProtobufRequestInfo requestInfo = new ProtobufRequestInfo(message);

                Reset();

                return requestInfo;
            }
            return default;
        }

        public void Reset()
        {
            swapBuffer = null;
            sumLength = 0;
            alreadySwap = 0;
        }
    }
}
